package com.android.kotlincoroutinemvvmdemo.view

import android.content.Context
import android.graphics.Camera
import android.graphics.Canvas
import android.graphics.Matrix
import android.graphics.Paint
import android.util.AttributeSet
import android.view.MotionEvent
import com.android.kotlincoroutinemvvmdemo.R

class Th3DView @JvmOverloads constructor(context: Context, attributeSet: AttributeSet? = null) :
    BaseView(context, attributeSet) {

    private var cx = 0F
    private var cy = 0F

    private var mCanvasRotateX = 0F
    private var mCanvasRotateY = 0F

    private val mCanvasMaxRotateDegree = 20F

    private val mMatrix by lazy {
        Matrix()
    }

    private val mCamera by lazy {
        Camera()
    }

    private val mPaint by lazy {
        Paint().apply {
            isAntiAlias = true
            isDither = true
            style = Paint.Style.FILL
            color = context.resources.getColor(R.color.color_E60C3F)
        }
    }

    override fun onDraw(canvas: Canvas?) {
        super.onDraw(canvas)
        cx = mWidth / 2.0F
        cy = mHeight / 2.0F

        canvas?.apply {
            rotateCanvas(this)
            drawCircle(cx, cy, cx, mPaint)
        }
    }

    override fun onTouchEvent(event: MotionEvent?): Boolean {
        performClick()
        when (event?.action) {
            MotionEvent.ACTION_DOWN,
            MotionEvent.ACTION_MOVE -> {
                rotateCanvasWhenMove(event.x, event.y)
            }
            MotionEvent.ACTION_UP -> {
                mCanvasRotateX = 0F
                mCanvasRotateY = 0F
            }
        }
        invalidate()
        return true
    }

    override fun performClick(): Boolean {
        return super.performClick()
    }

    private fun rotateCanvas(canvas: Canvas) {
        mMatrix.reset()
        mCamera.save()
        mCamera.rotateX(mCanvasRotateX)
        mCamera.rotateY(mCanvasRotateY)
        mCamera.getMatrix(mMatrix)
        mCamera.restore()

        mMatrix.preTranslate(-cx, -cy)
        mMatrix.postTranslate(cx, cy)

        canvas.concat(mMatrix)
    }

    private fun rotateCanvasWhenMove(x: Float, y: Float) {
        val dx = x - cx
        val dy = y - cy

        var percentX = dx / cx
        var percentY = dy / cy

        if (percentX > 1F) {
            percentX = 1F
        } else if (percentX < -1F) {
            percentX = -1F
        }

        if (percentY > 1F) {
            percentY = 1F
        } else if (percentY < -1F) {
            percentY = -1F
        }

        mCanvasRotateX = mCanvasMaxRotateDegree * percentX
        mCanvasRotateY = -(mCanvasMaxRotateDegree * percentY)
    }
}